﻿#region The MIT License
// The MIT License
// 
// Copyright (c) 2009 octalforty studios
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#endregion
using System;

using Irony.Ast;
using Irony.Parsing;

using NUnit.Framework;

using octalforty.Chinchillin.Console.Compiler;

namespace octalforty.Chinchillin.Tests.Core.Compiler
{
    [TestFixture()]
    public class CdmGrammarTestFixture
    {
        [Test()]
        public void Test()
        {
            var ast = Parse(@"def server name => web, address => ""192.168.0.98"", login => administrator, password => ""w3bs#rv@dm!n""
def server name => db, address => ""192.168.0.171""
def task name => foo:
  exec foo:bar name => [foo, [""bar"", 234, [23], 43], 3], value => ""sdf""
  exec foo:bar name => [foo, [""bar"", 234, [23], 43], 3]:
    rollback:
      exec foo:bar name => [foo, [""bar"", 234, [23], 43], 3]");
        }

        [Test()]
        public void ParseDeploymentManifestNode()
        {
            var parseTree = Parse(@"deployment-manifest version => ""1.0"", manifest-version => ""2.0""");

            var deploymentManifest = parseTree.Root.GetNode("deploymentManifest");
            Assert.IsNotNull(deploymentManifest);

            var propertyAssignmentList = deploymentManifest.GetNode("propertyAssignmentList");
            Assert.IsNotNull(propertyAssignmentList);

            var versionPropertyAssignment = propertyAssignmentList.GetNode("propertyAssignment");
            Assert.IsNotNull(versionPropertyAssignment);

            var version = versionPropertyAssignment.GetIdentifier("version");
            Assert.IsNotNull(version);

            var manifestVersionPropertyAssignment = propertyAssignmentList.GetNode("propertyAssignment", 1);
            Assert.IsNotNull(manifestVersionPropertyAssignment);

            var manifestVersion = manifestVersionPropertyAssignment.GetIdentifier("manifest-version");
            Assert.IsNotNull(manifestVersion);
        }

        [Test()]
        public void ParseDeploymentManifestNodeTree()
        {
            var parseTree = Parse(@"deployment-manifest version => ""1.0""
  def server name => web

  def task name => ""Deploy""
    exec fs:sync-directory source-location => ""local://./foo/"", target-location => ""web://c:/inetpub/wwwroot/foo/""

    rollback
        exec fs:delete-directory location => ""local://./foo/""
    end
  end
end");

            var serverDefinition = parseTree.Root.GetNode("serverDefinition");
            Assert.IsNotNull(serverDefinition);

            var taskDefinition = parseTree.Root.GetNode("taskDefinition");
            Assert.IsNotNull(taskDefinition);

            var actionExecution = taskDefinition.GetNode("actionExecution");
            Assert.IsNotNull(actionExecution);

            var rollbackBlock = actionExecution.GetNode("rollbackBlock");
            Assert.IsNotNull(rollbackBlock);
        }

        private static Parser CreateParser()
        {
            var grammar = new CdmGrammar();
            var parser = new Parser(grammar);

            return parser;
        }

        private static ParseTree Parse(string source)
        {
            try
            {
                var parseTree = CreateParser().Parse(source);

                if(parseTree.HasErrors())
                {
                    foreach(var parserMessage in parseTree.ParserMessages)
                        System.Console.WriteLine("{0} at {1}", parserMessage, parserMessage.Location);

                    Assert.Fail("{0} parser errors", parseTree.ParserMessages.Count);
                } // if

                return parseTree;
            }

            catch(Exception e)
            {
                Assert.Fail(e.ToString());
                return null;
            } // catch
        }
    }
}
